﻿using System;
using System.Collections.Specialized;
using System.Data;
using System.Linq;
using FileMonitor.Service.Configuration;
using FileMonitor.Service.Prototype;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;

namespace FileMonitor.Service.Provider.ProcessProvider
{
    public class FileMonitorProcessDatabaseProvider:FileMonitorProcessProviderBase
    {

        private SqlDatabase db;

        #region FileMonitorProcessProviderBase Members
        public override FileProcessProviderCollection GetAllProcess()
        {
            if (this.IsInitialize)
            {
                DataTable dtProcess = FileUtility.DBUtility.ReadAllFileMonitorProcess(this.db);
                FileProcessProviderCollection processs= this.ConstructProcessCollection(dtProcess);
                return processs;
            }
            else
            {
                throw new Exception("Must Initialize at first");
            }
         
        }
        public override void LockProcess(FileMonitorBase process)
        {
            if (this.IsInitialize)
            {
                string hostname = System.Net.Dns.GetHostName();
                System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(hostname);
                string ipaddress = ipEntry.AddressList[0].ToString();
                string lockedBy = hostname + "(" + ipaddress + ")";
                FileUtility.DBUtility.LockProcess(db, process.Name, lockedBy);
            }
            else
            {
                throw new Exception("Must Initialize at first");
            }
        }
        public override void Initialize(NameValueCollection config)
        {
            if (config["ProvderDBConnection"] == null)
            {
                throw new Exception("Must set ProvderDBConnection ");
            }
            else
                this.db = new SqlDatabase(config["ProvderDBConnection"]);

            base.Initialize(config);
        }
        #endregion

        public FileMonitorProcessDatabaseProvider() : base() { }

        #region Private Methods
        private FileProcessProviderCollection ConstructProcessCollection(DataTable dt)
        {
            try
            {
                FileProcessProviderCollection porcesss = new FileProcessProviderCollection();
                dt.AsEnumerable().ToList().ForEach((row) =>
                {
                    string processName = row["ProcessName"].ToString();
                    string typeName = row["MonitorProviderType"].ToString();
                    if (string.IsNullOrEmpty(processName) || string.IsNullOrEmpty(typeName))
                    {
                        throw new Exception("ProcessName&MonitorProviderType Can not be null");
                    }
                    string MonitorProviderType = System.Configuration.ConfigurationManager.AppSettings[typeName];
                    if (string.IsNullOrEmpty(MonitorProviderType))
                    {
                        throw new Exception("The MonitorProviderType not imlementetion .");
                    }
                    
                    FileMonitorBase base1 = null;
                    Type c = ProvidersHelper.GetType(MonitorProviderType, "type", null, null, true);
                    if (!typeof(FileMonitorBase).IsAssignableFrom(c))
                    {
                        throw new ArgumentException("Provider_must_implement_type:FileMonitorBase");
                    }
                    base1 = (FileMonitorBase)Activator.CreateInstance(c);
                    NameValueCollection config = FileMonitorProcessDatabaseProvider.InitialConfig(row);
                    config["MonitorProviderType"] = MonitorProviderType;
                    base1.Initialize(processName, config);
                    porcesss.Add(base1);
                });
                return porcesss;
            }
            catch(Exception ex)
            {
                throw new Exception(ex.Message);
            }
         
        }

        private static NameValueCollection InitialConfig(DataRow dr)
        {
            NameValueCollection values = new NameValueCollection();
            foreach (DataColumn col in dr.Table.Columns)
            {
                string colName = col.ColumnName.ToUpper();
                values.Add(colName, dr[col].ToString());
            }
            return values;
        }
        #endregion
    }
}
